From 231be096c3b25b0c30859d18613aaa6eb50ce050 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Fri, 15 Apr 2005 23:40:59 +0000 Subject: [PATCH] bitkeeper revision 1.1308 (4260510bQdQyEJ4w-XdZSU5iSTB_Pg) The attached patch apic.patch updates xen/arch/x86/apic.c so that it is based on linux 2.6.10 code. A few changes made to linux required reworking functions in other files as well so I held off on those changes. For example, setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int). The change has no real bearing on the Xen code -- it's just a question of how close to linux one wants to be. However, that change goes with a change to smp_call_function which would affect quite a few other files/functions so I left it as is. Most of the other changes are trivial. xen/ac_timer.h was included but not needed by apic.c so I removed it from the list of #includes. The new apic.c includes two new files: asm/io_ports.h and asm/mach_apic.h. Patches to create those files are included as well. --- .rootkeys | 2 + xen/arch/x86/apic.c | 370 +++++++++++++++++++++++--------- xen/include/asm-x86/io_ports.h | 30 +++ xen/include/asm-x86/mach_apic.h | 32 +++ 4 files changed, 328 insertions(+), 106 deletions(-) create mode 100644 xen/include/asm-x86/io_ports.h create mode 100644 xen/include/asm-x86/mach_apic.h diff --git a/.rootkeys b/.rootkeys index 95fbaf200c..6c7e1b4232 100644 --- a/.rootkeys +++ b/.rootkeys @@ -1323,8 +1323,10 @@ 4204e7acwXDo-5iAAiO2eQbtDeYZXA xen/include/asm-x86/init.h 3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-x86/io.h 3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-x86/io_apic.h +42605109qxLSrHVE2SRhGXmgk907iw xen/include/asm-x86/io_ports.h 3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-x86/irq.h 404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-x86/ldt.h +4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach_apic.h 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-x86/mc146818rtc.h 40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h 3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 49b51ba012..9b44fb6f98 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -1,4 +1,6 @@ /* + * based on linux-2.6.10/arch/i386/kernel/apic.c + * * Local APIC handling, local APIC timers * * (c) 1999, 2000 Ingo Molnar @@ -10,11 +12,11 @@ * for testing these extensively. * Maciej W. Rozycki : Various updates and fixes. * Mikael Pettersson : Power Management for UP-APIC. + * Pavel Machek and + * Mikael Pettersson : PM converted to driver model. */ - #include -#include #include #include #include @@ -32,7 +34,8 @@ #include #include #include - +#include +#include /* Using APIC to generate smp_local_timer_interrupt? */ int using_apic_timer = 0; @@ -80,6 +83,16 @@ void clear_local_APIC(void) apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED); } +#if 0 +/* lets not touch this if we didn't frob it */ +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) { + v = apic_read(APIC_LVTTHMR); + apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED); + } +#endif +#endif + /* * Clean APIC state for other OSs: */ @@ -90,9 +103,17 @@ void clear_local_APIC(void) apic_write_around(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) apic_write_around(APIC_LVTPC, APIC_LVT_MASKED); + +#if 0 +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) + apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED); +#endif +#endif + v = GET_APIC_VERSION(apic_read(APIC_LVR)); if (APIC_INTEGRATED(v)) { /* !82489DX */ - if (maxlvt > 3) + if (maxlvt > 3) /* Due to Pentium errata 3AP and 11AP. */ apic_write(APIC_ESR, 0); apic_read(APIC_ESR); } @@ -113,6 +134,9 @@ void __init connect_bsp_APIC(void) outb(0x70, 0x22); outb(0x01, 0x23); } +#if 0 + enable_apic_mode(); +#endif } void disconnect_bsp_APIC(void) @@ -193,12 +217,6 @@ int __init verify_local_APIC(void) */ reg0 = apic_read(APIC_ID); Dprintk("Getting ID: %x\n", reg0); - apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); - reg1 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg1); - apic_write(APIC_ID, reg0); - if (reg1 != (reg0 ^ APIC_ID_MASK)) - return 0; /* * The next two are just to see if we have sane values. @@ -215,6 +233,10 @@ int __init verify_local_APIC(void) void __init sync_Arb_IDs(void) { + /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */ + unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + if (ver >= 0x14) /* P4 or higher */ + return; /* * Wait for idle. */ @@ -240,15 +262,17 @@ void __init init_bsp_APIC(void) { } -static unsigned long calculate_ldr(unsigned long old) -{ - unsigned long id = 1UL << smp_processor_id(); - return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id); -} - void __init setup_local_APIC (void) { - unsigned long value, ver, maxlvt; + unsigned long oldvalue, value, ver, maxlvt; + + /* Pound the ESR really hard over the head with a big hammer - mbligh */ + if (esr_disable) { + apic_write(APIC_ESR, 0); + apic_write(APIC_ESR, 0); + apic_write(APIC_ESR, 0); + apic_write(APIC_ESR, 0); + } value = apic_read(APIC_LVR); ver = GET_APIC_VERSION(value); @@ -256,8 +280,10 @@ void __init setup_local_APIC (void) if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f) __error_in_apic_c(); - /* Double-check wether this APIC is really registered. */ - if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map)) + /* + * Double-check whether this APIC is really registered. + */ + if (!apic_id_registered()) BUG(); /* @@ -265,19 +291,7 @@ void __init setup_local_APIC (void) * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel * document number 292116). So here it goes... */ - - /* - * In clustered apic mode, the firmware does this for us - * Put the APIC into flat delivery mode. - * Must be "all ones" explicitly for 82489DX. - */ - apic_write_around(APIC_DFR, APIC_DFR_FLAT); - - /* - * Set up the logical destination ID. - */ - value = apic_read(APIC_LDR); - apic_write_around(APIC_LDR, calculate_ldr(value)); + init_apic_ldr(); /* * Set Task Priority to 'accept all'. We never change this @@ -297,10 +311,35 @@ void __init setup_local_APIC (void) */ value |= APIC_SPIV_APIC_ENABLED; + /* + * Some unknown Intel IO/APIC (or APIC) errata is biting us with + * certain networking cards. If high frequency interrupts are + * happening on a particular IOAPIC pin, plus the IOAPIC routing + * entry is masked/unmasked at a high rate as well then sooner or + * later IOAPIC line gets 'stuck', no more interrupts are received + * from the device. If focus CPU is disabled then the hang goes + * away, oh well :-( + * + * [ This bug can be reproduced easily with a level-triggered + * PCI Ne2000 networking cards and PII/PIII processors, dual + * BX chipset. ] + */ + /* + * Actually disabling the focus CPU check just makes the hang less + * frequent as it makes the interrupt distributon model be more + * like LRU than MRU (the short-term load is more even across CPUs). + * See also the comment in end_level_ioapic_irq(). --macro + */ +#if 1 /* Enable focus processor (bit==0) */ value &= ~APIC_SPIV_FOCUS_DISABLED; - - /* Set spurious IRQ vector */ +#else + /* Disable focus processor (bit==1) */ + value |= APIC_SPIV_FOCUS_DISABLED; +#endif + /* + * Set spurious IRQ vector + */ value |= SPURIOUS_APIC_VECTOR; apic_write_around(APIC_SPIV, value); @@ -315,7 +354,7 @@ void __init setup_local_APIC (void) * TODO: set up through-local-APIC from through-I/O-APIC? --macro */ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; - if (!smp_processor_id()) { + if (!smp_processor_id() && (pic_mode || !value)) { value = APIC_DM_EXTINT; printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); } else { @@ -335,33 +374,43 @@ void __init setup_local_APIC (void) value |= APIC_LVT_LEVEL_TRIGGER; apic_write_around(APIC_LVT1, value); - if (APIC_INTEGRATED(ver)) { /* !82489DX */ + if (APIC_INTEGRATED(ver) && !esr_disable) { /* !82489DX */ maxlvt = get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - printk("ESR value before enabling vector: %08lx\n", value); + oldvalue = apic_read(APIC_ESR); - value = ERROR_APIC_VECTOR; /* enables sending errors */ + value = ERROR_APIC_VECTOR; // enables sending errors apic_write_around(APIC_LVTERR, value); - /* spec says clear errors after enabling vector. */ + /* + * spec says clear errors after enabling vector. + */ if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - printk("ESR value after enabling vector: %08lx\n", value); + if (value != oldvalue) + printk("ESR value before enabling vector: 0x%08lx " + "after: 0x%08lx\n", oldvalue, value); } else { + if (esr_disable) + /* + * Something untraceble is creating bad interrupts on + * secondary quads ... for the moment, just leave the + * ESR disabled - we can't do anything useful with the + * errors anyway - mbligh + */ + printk("Leaving ESR disabled.\n"); + else printk("No ESR for 82489DX.\n"); } - if ( (smp_processor_id() == 0) && (nmi_watchdog == NMI_LOCAL_APIC) ) + if (nmi_watchdog == NMI_LOCAL_APIC) setup_apic_nmi_watchdog(); +#if 0 + apic_pm_activate(); +#endif } - -static inline void apic_pm_init1(void) { } -static inline void apic_pm_init2(void) { } - - /* * Detect and enable local APICs on non-SMP boards. * Original code written by Keir Fraser. @@ -372,19 +421,23 @@ static int __init detect_init_APIC (void) u32 h, l, features; extern void get_cpu_vendor(struct cpuinfo_x86*); +#if 0 + /* Disabled by kernel option? */ + if (enable_local_apic < 0) + return -1; +#endif + /* Workaround for us being called before identify_cpu(). */ get_cpu_vendor(&boot_cpu_data); switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: - if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) - break; - if (boot_cpu_data.x86 == 15 && cpu_has_apic) + if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) || + (boot_cpu_data.x86 == 15)) break; goto no_apic; case X86_VENDOR_INTEL: - if (boot_cpu_data.x86 == 6 || - (boot_cpu_data.x86 == 15 && cpu_has_apic) || + if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 || (boot_cpu_data.x86 == 5 && cpu_has_apic)) break; goto no_apic; @@ -393,10 +446,22 @@ static int __init detect_init_APIC (void) } if (!cpu_has_apic) { + /* + * Over-ride BIOS and try to enable the local + * APIC only if "lapic" specified. + */ +#if 0 + if (enable_local_apic <= 0) { + printk("Local APIC disabled by BIOS -- " + "you can enable it with \"lapic\"\n"); + return -1; + } +#endif /* * Some BIOSes disable the local APIC in the * APIC_BASE MSR. This can only be done in - * software for Intel P6 and AMD K7 (Model > 1). + * software for Intel P6 or later and AMD K7 + * (Model > 1) or later. */ rdmsr(MSR_IA32_APICBASE, l, h); if (!(l & MSR_IA32_APICBASE_ENABLE)) { @@ -407,17 +472,17 @@ static int __init detect_init_APIC (void) enabled_via_apicbase = 1; } } - - /* The APIC feature bit should now be enabled in `cpuid' */ + /* + * The APIC feature bit should now be enabled + * in `cpuid' + */ features = cpuid_edx(1); if (!(features & (1 << X86_FEATURE_APIC))) { printk("Could not enable APIC!\n"); return -1; } - - set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability); + set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; - boot_cpu_physical_apicid = 0; /* The BIOS may have set up the APIC at some other address */ rdmsr(MSR_IA32_APICBASE, l, h); @@ -428,21 +493,26 @@ static int __init detect_init_APIC (void) nmi_watchdog = NMI_LOCAL_APIC; printk("Found and enabled local APIC!\n"); - apic_pm_init1(); + +#if 0 + apic_pm_activate(); +#endif + return 0; - no_apic: +no_apic: printk("No local APIC present or hardware disabled\n"); return -1; } void __init init_apic_mappings(void) { - unsigned long apic_phys = 0; + unsigned long apic_phys; /* - * If no local APIC can be found then set up a fake all zeroes page to - * simulate the local APIC and another one for the IO-APIC. + * If no local APIC can be found then set up a fake all + * zeroes page to simulate the local APIC and another + * one for the IO-APIC. */ if (!smp_found_config && detect_init_APIC()) { apic_phys = alloc_xenheap_page(); @@ -462,12 +532,26 @@ void __init init_apic_mappings(void) #ifdef CONFIG_X86_IO_APIC { - unsigned long ioapic_phys = 0, idx = FIX_IO_APIC_BASE_0; + unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; int i; for (i = 0; i < nr_ioapics; i++) { - if (smp_found_config) + if (smp_found_config) { ioapic_phys = mp_ioapics[i].mpc_apicaddr; + if (!ioapic_phys) { + printk(KERN_ERR + "WARNING: bogus zero IO-APIC " + "address found in MPTABLE, " + "disabling IO/APIC support!\n"); + smp_found_config = 0; + skip_ioapic_setup = 1; + goto fake_ioapic_page; + } + } else { +fake_ioapic_page: + ioapic_phys = alloc_xenheap_page(); + ioapic_phys = __pa(ioapic_phys); + } set_fixmap_nocache(idx, ioapic_phys); Dprintk("mapped IOAPIC to %08lx (%08lx)\n", fix_to_virt(idx), ioapic_phys); @@ -504,32 +588,48 @@ static unsigned int __init get_8254_timer_count(void) { /*extern spinlock_t i8253_lock;*/ /*unsigned long flags;*/ + unsigned int count; + /*spin_lock_irqsave(&i8253_lock, flags);*/ - outb_p(0x00, 0x43); - count = inb_p(0x40); - count |= inb_p(0x40) << 8; + + outb_p(0x00, PIT_MODE); + count = inb_p(PIT_CH0); + count |= inb_p(PIT_CH0) << 8; + /*spin_unlock_irqrestore(&i8253_lock, flags);*/ + return count; } -void __init wait_8254_wraparound(void) +/* next tick in 8254 can be caught by catching timer wraparound */ +static void __init wait_8254_wraparound(void) { unsigned int curr_count, prev_count=~0; int delta; + curr_count = get_8254_timer_count(); + do { prev_count = curr_count; curr_count = get_8254_timer_count(); delta = curr_count-prev_count; + /* - * This limit for delta seems arbitrary, but it isn't, it's slightly - * above the level of error a buggy Mercury/Neptune chipset timer can - * cause. + * This limit for delta seems arbitrary, but it isn't, it's + * slightly above the level of error a buggy Mercury/Neptune + * chipset timer can cause. */ + } while (delta < 300); } +/* + * Default initialization for 8254 timers. If we use other timers like HPET, + * we override this later + */ +void (*wait_timer_tick)(void) = wait_8254_wraparound; + /* * This function sets up the local APIC timer, with a timeout of * 'clocks' APIC bus clock. During calibration we actually call @@ -541,14 +641,32 @@ void __init wait_8254_wraparound(void) * We do reads before writes even if unnecessary, to get around the * P5 APIC double write bug. */ + #define APIC_DIVISOR 1 + static void __setup_APIC_LVTT(unsigned int clocks) { - unsigned int lvtt1_value, tmp_value; - lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV)|LOCAL_TIMER_VECTOR; - apic_write_around(APIC_LVTT, lvtt1_value); + unsigned int lvtt_value, tmp_value, ver; + + ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; + if (!APIC_INTEGRATED(ver)) + lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); + apic_write_around(APIC_LVTT, lvtt_value); + +#if 0 + /* + * Divide PICLK by 16 + */ + tmp_value = apic_read(APIC_TDCR); + apic_write_around(APIC_TDCR, (tmp_value + & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) + | APIC_TDR_DIV_16); +#endif + tmp_value = apic_read(APIC_TDCR); apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1)); + apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR); } @@ -569,7 +687,7 @@ void setup_APIC_timer(void * data) /* * In this function we calibrate APIC bus clocks to the external timer. * - * As a result we have the Bys Speed and CPU speed in Hz. + * As a result we have the Bus Speed and CPU speed in Hz. * * We want to do the calibration only once (for CPU0). CPUs connected by the * same APIC bus have the very same bus frequency. @@ -586,48 +704,61 @@ int __init calibrate_APIC_clock(void) int i; const int LOOPS = HZ/10; +#if 0 + apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n"); +#endif printk("Calibrating APIC timer for CPU%d...\n", smp_processor_id()); - /* Put whatever arbitrary (but long enough) timeout + /* + * Put whatever arbitrary (but long enough) timeout * value into the APIC clock, we just want to get the - * counter running for calibration. */ + * counter running for calibration. + */ __setup_APIC_LVTT(1000000000); - /* The timer chip counts down to zero. Let's wait + /* + * The timer chip counts down to zero. Let's wait * for a wraparound to start exact measurement: - * (the current tick might have been already half done) */ - wait_8254_wraparound(); + * (the current tick might have been already half done) + */ - /* We wrapped around just now. Let's start: */ + wait_timer_tick(); + + /* + * We wrapped around just now. Let's start: + */ + if (cpu_has_tsc) rdtscll(t1); tt1 = apic_read(APIC_TMCCT); - /* Let's wait LOOPS wraprounds: */ + /* + * Let's wait LOOPS wraprounds: + */ for (i = 0; i < LOOPS; i++) - wait_8254_wraparound(); + wait_timer_tick(); tt2 = apic_read(APIC_TMCCT); + if (cpu_has_tsc) rdtscll(t2); - /* The APIC bus clock counter is 32 bits only, it + /* + * The APIC bus clock counter is 32 bits only, it * might have overflown, but note that we use signed * longs, thus no extra care needed. - * underflown to be exact, as the timer counts down ;) */ - result = (tt1-tt2)*APIC_DIVISOR/LOOPS; + * + * underflown to be exact, as the timer counts down ;) + */ - printk("..... CPU speed is %ld.%04ld MHz.\n", - ((long)(t2-t1)/LOOPS) / (1000000/HZ), - ((long)(t2-t1)/LOOPS) % (1000000/HZ)); + result = (tt1-tt2)*APIC_DIVISOR/LOOPS; - printk("..... Bus speed is %ld.%04ld MHz.\n", - result / (1000000/HZ), - result % (1000000/HZ)); + if (cpu_has_tsc) + printk("..... CPU clock speed is %ld.%04ld MHz.\n", + ((long)(t2-t1)/LOOPS)/(1000000/HZ), + ((long)(t2-t1)/LOOPS)%(1000000/HZ)); - /* - * KAF: Moved this to time.c where it's calculated relative to the TSC. - * Therefore works on machines with no local APIC. - */ - /*cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);*/ + printk("..... host bus clock speed is %ld.%04ld MHz.\n", + result/(1000000/HZ), + result%(1000000/HZ)); /* set up multipliers for accurate timer code */ bus_freq = result*HZ; @@ -637,6 +768,7 @@ int __init calibrate_APIC_clock(void) printk("..... bus_scale = 0x%08X\n", bus_scale); /* reset APIC to zero timeout value */ __setup_APIC_LVTT(0); + return result; } @@ -729,13 +861,17 @@ void smp_apic_timer_interrupt(struct xen_regs * regs) raise_softirq(AC_TIMER_SOFTIRQ); } + /* * This interrupt should _never_ happen with our APIC/SMP architecture */ -asmlinkage void smp_spurious_interrupt(void) +asmlinkage void smp_spurious_interrupt(struct xen_regs *regs) { unsigned long v; +#if 0 + irq_enter(); +#endif /* * Check if this really is a spurious interrupt and ACK it * if it is a vectored one. Just in case... @@ -748,16 +884,22 @@ asmlinkage void smp_spurious_interrupt(void) /* see sw-dev-man vol 3, chapter 7.4.13.5 */ printk("spurious APIC interrupt on CPU#%d, should never happen.\n", smp_processor_id()); +#if 0 + irq_exit(); +#endif } /* * This interrupt should never happen with our APIC/SMP architecture */ -asmlinkage void smp_error_interrupt(void) +asmlinkage void smp_error_interrupt(struct xen_regs *regs) { unsigned long v, v1; +#if 0 + irq_enter(); +#endif /* First tickle the hardware, only then report what went on. -- REW */ v = apic_read(APIC_ESR); apic_write(APIC_ESR, 0); @@ -775,8 +917,11 @@ asmlinkage void smp_error_interrupt(void) 6: Received illegal vector 7: Illegal register address */ - printk ("APIC error on CPU%d: %02lx(%02lx)\n", + Dprintk("APIC error on CPU%d: %02lx(%02lx)\n", smp_processor_id(), v , v1); +#if 0 + irq_exit(); +#endif } /* @@ -785,14 +930,18 @@ asmlinkage void smp_error_interrupt(void) */ int __init APIC_init_uniprocessor (void) { +#if 0 + if (enable_local_apic < 0) + clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability); +#endif + if (!smp_found_config && !cpu_has_apic) return -1; /* * Complain if the BIOS pretends there is one. */ - if (!cpu_has_apic&&APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) - { + if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) { printk("BIOS bug, local APIC #%d not detected!...\n", boot_cpu_physical_apicid); return -1; @@ -804,17 +953,26 @@ int __init APIC_init_uniprocessor (void) #ifdef CONFIG_SMP cpu_online_map = 1; +#endif +#if 0 + phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); #endif phys_cpu_present_map = 1; apic_write_around(APIC_ID, boot_cpu_physical_apicid); - apic_pm_init2(); - setup_local_APIC(); +#if 0 + if (nmi_watchdog == NMI_LOCAL_APIC) + check_nmi_watchdog(); +#endif #ifdef CONFIG_X86_IO_APIC - if (smp_found_config && nr_ioapics) + if (smp_found_config) + if (!skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); +#endif +#if 0 + setup_boot_APIC_clock(); #endif setup_APIC_clocks(); diff --git a/xen/include/asm-x86/io_ports.h b/xen/include/asm-x86/io_ports.h new file mode 100644 index 0000000000..db490bd142 --- /dev/null +++ b/xen/include/asm-x86/io_ports.h @@ -0,0 +1,30 @@ +/* + * based on linux-2.6.10/include/asm-i386/mach-default/io_ports.h + * + * Machine specific IO port address definition for generic. + * Written by Osamu Tomita + */ +#ifndef _MACH_IO_PORTS_H +#define _MACH_IO_PORTS_H + +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 + +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_IMR 0x21 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_IMR 0xa1 + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 +#define PIC_ICW4_AEOI 2 + +#endif /* !_MACH_IO_PORTS_H */ diff --git a/xen/include/asm-x86/mach_apic.h b/xen/include/asm-x86/mach_apic.h new file mode 100644 index 0000000000..e93b0808d5 --- /dev/null +++ b/xen/include/asm-x86/mach_apic.h @@ -0,0 +1,32 @@ +/* + * based on linux-2.6.10/include/asm-i386/mach-default/mach_apic.h + * + */ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +#define APIC_DFR_VALUE (APIC_DFR_FLAT) +#define esr_disable (0) + +/* + * Set up the logical destination ID. + * + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ +static inline void init_apic_ldr(void) +{ + unsigned long val; + + apic_write_around(APIC_DFR, APIC_DFR_VALUE); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); + apic_write_around(APIC_LDR, val); +} + +static inline int apic_id_registered(void) +{ + return test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map); +} +#endif /* __ASM_MACH_APIC_H */ -- 2.30.2